<?php
declare(strict_types=1);

namespace lib;
/**
 * 文件上传类
 * 图片服务器的接口封装.
 */

class ExtiStorage {
    /**
     * 服务器地址
     */
    protected static $base_url = 'https://file.80mall.net';
    //protected static $base_url = 'https://file.exti.cc';
    /**
     * 分片大小
     */
    protected static $slice_size = 1024000; 
    /**
     * @param string $bucket
    */
    public static function save(string $bucket, string $content, $meta = null) : array {
        if(ord($content[0]) == 0xFF && ord($content[1]) == 0xD8 && ord($content[2]) == 0xFF){ # JPG
            $mime = 'image/jpg';
        }elseif(ord($content[0]) == 0x89 && ord($content[1]) == 0x50 && ord($content[2]) == 0x4E && ord($content[3]) == 0x47){ // PNG
            $mime = 'image/png';
        }elseif(ord($content[0]) == 0x47 && ord($content[1]) == 0x49 && ord($content[2]) == 0x46 && ord($content[3]) == 0x38){ // GIF
            $mime = 'image/gif';
        }elseif(ord($content[0]) == 0x49 && ord($content[1]) == 0x49 && ord($content[2]) == 0x2A && ord($content[3]) == 0x00){ // TIFF
            $mime = 'image/tiff';
        }elseif(ord($content[0]) == 0x52 && ord($content[1]) == 0x49 && ord($content[2]) == 0x46 && ord($content[3]) == 0x46){ // WEBP
            $mime = 'image/webp';
        }elseif(ord($content[0]) == 0x42 && ord($content[1]) == 0x4D){ // BMP
            $mime = 'image/bmp';
        }else{
            return ['success'=>false, 'message'=>'文件类型不支持'];
        }
        $retu = http_post(static::$base_url . '/json/save', json_encode([
            'bucket'=>$bucket,
            'files'=>[
                'file'=>[
                    'file'=>'data:' . $mime . ';base64,' . base64_encode($content),
                    'meta'=>$meta
                ]
            ]
        ],JSON_UNESCAPED_UNICODE));
        if(200 == $retu['code']){
            $ret = json_decode($retu['body'], true);
            if(true === $ret['success']){
                return ['success'=>$ret['success'], 'file'=>$ret['files']['file']];
            }
            return ['success'=>$ret['success'], 'message'=> $ret['message']];
        }
        return ['success'=>false,'message'=>'网关调用出错.'];
    }


    /**
     * 使用 http 上传文件
     */
    public static function upload(string $bucket, string $file, $meta = null) : array {
        $totale_size = filesize($file);

        # 文件超过了大小 自动切片上传
        if($totale_size >= static::$slice_size){
            return static::slicesave($bucket, $file, $meta);
        }

        $mime = mime_content_type($file);
        $post = [
            'bucket'=>$bucket,
            'meta' => json_encode($meta, JSON_UNESCAPED_UNICODE),
            'file'=>new \sys\UploadFile($file, $mime, $file, true)
        ];
        $retu = http_post(static:: $base_url . '/http/save', $post);
        if($retu['code'] == 200){
            $body = json_decode($retu['body'], true);
            if($body['success']){
                return ['success'=>true, 'file'=>$body['file']];
            }
            return ['success'=>$body['success'], 'message'=>$body['message']];
        }
        return ['success'=>false, 'message'=>'网关错误'];
    }

    /**
     * 使用 http 上传文件
     */
    public static function uploadstr(string $bucket, string $content, $meta = null) : array {


        if(ord($content[0]) == 0xFF && ord($content[1]) == 0xD8 && ord($content[2]) == 0xFF){ # JPG
            $mime = 'image/jpg';
            $ext = '.jpg';
        }elseif(ord($content[0]) == 0x89 && ord($content[1]) == 0x50 && ord($content[2]) == 0x4E && ord($content[3]) == 0x47){ // PNG
            $mime = 'image/png';
            $ext = '.png';
        }elseif(ord($content[0]) == 0x47 && ord($content[1]) == 0x49 && ord($content[2]) == 0x46 && ord($content[3]) == 0x38){ // GIF
            $mime = 'image/gif';
            $ext = '.gif';
        }elseif(ord($content[0]) == 0x49 && ord($content[1]) == 0x49 && ord($content[2]) == 0x2A && ord($content[3]) == 0x00){ // TIFF
            $mime = 'image/tiff';
            $ext = '.tiff';
        }elseif(ord($content[0]) == 0x52 && ord($content[1]) == 0x49 && ord($content[2]) == 0x46 && ord($content[3]) == 0x46){ // WEBP
            $mime = 'image/webp';
            $ext = '.webp';
        }elseif(ord($content[0]) == 0x42 && ord($content[1]) == 0x4D){ // BMP
            $mime = 'image/bmp';
            $ext = '.bmp';
        }else{
            return ['success'=>false, 'message'=>'文件类型不支持'];
        }

        $post = [
            'bucket'=>$bucket,
            'meta' => json_encode($meta, JSON_UNESCAPED_UNICODE),
            'file'=>new \sys\UploadFile($content, $mime, time().$ext,  false)
        ];
        $retu = http_post(static::$base_url . '/http/save', $post);
        if($retu['code'] == 200){
            $body = json_decode($retu['body'], true);
            if($body['success']){
                return ['success'=>true, 'file'=>$body['files']['file']];
            }
            return ['success'=>$body['success'], 'message'=>$body['message']];
        }
        return ['success'=>false, 'message'=>'网关错误'];
    }

    /**
     * 大文件分包上传
     */
    public static function slicesave(string $bucket, string $file, $meta = null) : array
    {
        $uploaded = 0; $index = 0; $sid = null;
        $total_size = filesize($file);
        $mime = mime_content_type($file);
        $name = '';
        $body = null;
        $fp = fopen($file, 'rb', false);
        $sid = null;

        $curl = curl_init();
        while($uploaded < $total_size){
            $post = [];
            $size = min(static::$slice_size, $total_size - $uploaded);
            if($uploaded == 0){
                $post['bucket'] = $bucket;
                $post['size'] = $total_size;
                $post['type'] = $mime;
            }else{
                $post['type'] = $mime;
                $post['name'] = $name;
            }

            if($size + $uploaded == $total_size){
                $post['meta'] = json_encode($meta, JSON_UNESCAPED_UNICODE);
            }

            # 读取部分数据
            $parts = fread($fp, $size);
            
            $post['file'] = new \sys\UploadFile($parts, $file, $mime, false);
            
            if($sid != null ) $headers = ['X-Sid'=>$sid]; else $headers = null;
            $retu = http_post(static::$base_url.'/http/slicesave', $post, $headers);
          
            if($retu['code'] == 200)
            {
                $body = json_decode($retu['body'], true);
                if($body['success']){
                    $uploaded += $size;
                    $body['file'] = $name = $body['file'] ?? $name;

                    if(0 == $index && isset($body['sid'])){
                        $sid = $body['sid'];
                    }
                    $index ++;
                    continue;
                }else{
                    return $body;
                }
            }
            $body = ['success'=>false, 'message'=>'网关错误'];
            break;
        }
        curl_close($curl);
        return $body;
    }


    /**
     * 设置元数据.
     * @param string $file 要设置元数据的文件
     * @param array meta   要设置的元数据 null 表示删除元数据. 'expire' 表示文件过期时间.
     */
    public static function setmeta(string $file, $meta = null) :bool {
        $retu = http_post(static::$base_url . '/json/setmeta', json_encode([
            $file=>$meta
        ],JSON_UNESCAPED_UNICODE));
        if($retu['code'] === 200){
            $body = json_decode($retu['body'], true);
            if($body['success']){
                return $body['result'][$file];
            }
        }
        return false;
    }

    /**
     * 获取元数据
     * @param string $file 要获取meta的文件.
     * @return array 包含 success meta 两个属性
     */
    public static function getmeta(string $file) : array {
        $retu = http_post(static::$base_url . '/json/getmeta', json_encode([
            $file
        ],JSON_UNESCAPED_UNICODE));
        if($retu['code'] === 200){
            $body = json_decode($retu['body'], true);
            if($body['success']){
                return ['success'=>$body['success'], 'meta'=>$body['result'][$file]];
            }
            return $body;
        }
        return ['success'=>false, 'message'=>'网关错误'];
    }

    /**
     * 删除文件
     * @param string|array $file 要删除的文件
     * @return true|false 成功返回 true 失败 返回 false
     */
    public static function delete($file) : array {
        if(!is_array($file)){
            $xfile = [$file];
            $is_multi = false;
        }else{
            $xfile = $file;
            $is_multi = true;
        }

        $retu = http_post(static::$base_url . '/json/delete', json_encode($xfile,JSON_UNESCAPED_UNICODE));
        if($retu['code'] === 200){
            $body = json_decode($retu['body'], true);
            if($body['success']){
                if($is_multi){
                    return ['success'=>true, 'result'=>$body['result']];
                }
                return ['success'=>$body['result'][$file] ?? false];
            }
        }
        return ['success'=>false, 'message'=>'网关错误'];
    }

    /**
     * 获取配置接口
     */
    public static function info(string $bucket) : array
    {
        $retu = http_post(static::$base_url . '/json/config', json_encode(['bucket'=>$bucket],JSON_UNESCAPED_UNICODE));
        if($retu['code'] === 200){
            $body = json_decode($retu['body'], true);
            return $body;
        }
        return ['success'=>false, 'message'=>'网关错误'];
    }
}
